#pragma once
#include <curl/curl.h>
#include <sstream>
#include <memory>
#include "logger.hpp"
#include <gflags/gflags.h>

namespace ltn {
    // 邮件服务配置结构体
    struct mail_settings {
        std::string username;  // 授权邮箱账号
        std::string password;  // 客户端授权码
        std::string url;       // 邮件服务器地址（如smtps://smtp.163.com:465）
        std::string from;      // 发送方邮箱地址
    };

    // 验证码发送客户端基类
    class CodeClient {
    public:
        CodeClient() = default;
        virtual ~CodeClient() = default;
        // 纯虚函数：发送验证码（子类实现具体逻辑）
        virtual bool send(const std::string& to, const std::string& code) = 0;
    };

    // 邮件客户端类（继承自验证码客户端）
    class MailClient : public CodeClient {
    public:
        using ptr = std::shared_ptr<MailClient>;  // 智能指针类型定义

        // 构造函数：初始化CURL全局配置，保存邮件服务设置
        MailClient(const mail_settings& settings) : _settings(settings) {
            auto ret = curl_global_init(CURL_GLOBAL_DEFAULT);
            if (ret != CURLE_OK) {
                LOG_ERROR("初始化CURL全局配置失败: {}", curl_easy_strerror(ret));
                abort();  // 初始化失败则终止程序
            }
        }

        // 析构函数：释放CURL全局资源
        ~MailClient() override {
            curl_global_cleanup();
        }

        // 发送邮件实现（重写基类纯虚函数）
        bool send(const std::string& to, const std::string& code) override {
            // 创建CURL操作句柄
            CURL* curl = curl_easy_init();
            if (curl == nullptr) {
                LOG_ERROR("构造CURL操作句柄失败!");
                return false;
            }

            // // 设置CURL参数
            // curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15L);  // 连接超时15秒
            // curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);         // 总超时30秒
            // // 测试阶段关闭SSL证书验证（生产环境需开启）
            // curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
            // curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

            // 设置邮件服务器地址
            auto ret = curl_easy_setopt(curl, CURLOPT_URL, _settings.url.c_str());
            if (ret != CURLE_OK) {
                LOG_ERROR("设置CURLOPT_URL失败: {}", curl_easy_strerror(ret));
                curl_easy_cleanup(curl);
                return false;
            }

            // 设置邮箱账号和授权码
            ret = curl_easy_setopt(curl, CURLOPT_USERNAME, _settings.username.c_str());
            if (ret != CURLE_OK) {
                LOG_ERROR("设置CURLOPT_USERNAME失败: {}", curl_easy_strerror(ret));
                curl_easy_cleanup(curl);
                return false;
            }
            ret = curl_easy_setopt(curl, CURLOPT_PASSWORD, _settings.password.c_str());
            if (ret != CURLE_OK) {
                LOG_ERROR("设置CURLOPT_PASSWORD失败: {}", curl_easy_strerror(ret));
                curl_easy_cleanup(curl);
                return false;
            }

            // 设置发件人
            ret = curl_easy_setopt(curl, CURLOPT_MAIL_FROM, _settings.from.c_str());
            if (ret != CURLE_OK) {
                LOG_ERROR("设置CURLOPT_MAIL_FROM失败: {}", curl_easy_strerror(ret));
                curl_easy_cleanup(curl);
                return false;
            }

            // 设置收件人列表
            struct curl_slist* recipients = nullptr;
            recipients = curl_slist_append(recipients, to.c_str());
            ret = curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
            if (ret != CURLE_OK) {
                LOG_ERROR("设置CURLOPT_MAIL_RCPT失败: {}", curl_easy_strerror(ret));
                curl_slist_free_all(recipients);
                curl_easy_cleanup(curl);
                return false;
            }

            // 构造邮件正文并设置数据读取回调
            std::stringstream body = codeBody(to, code);
            ret = curl_easy_setopt(curl, CURLOPT_READDATA, &body);  // 数据源（邮件正文）
            if (ret != CURLE_OK) {
                LOG_ERROR("设置CURLOPT_READDATA失败: {}", curl_easy_strerror(ret));
                curl_slist_free_all(recipients);
                curl_easy_cleanup(curl);
                return false;
            }
            ret = curl_easy_setopt(curl, CURLOPT_READFUNCTION, &MailClient::callback);  // 读取回调
            if (ret != CURLE_OK) {
                LOG_ERROR("设置CURLOPT_READFUNCTION失败: {}", curl_easy_strerror(ret));
                curl_slist_free_all(recipients);
                curl_easy_cleanup(curl);
                return false;
            }

            // 启用上传模式（SMTP发送邮件本质是上传数据）
            ret = curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
            if (ret != CURLE_OK) {
                LOG_ERROR("设置CURLOPT_UPLOAD失败: {}", curl_easy_strerror(ret));
                curl_slist_free_all(recipients);
                curl_easy_cleanup(curl);
                return false;
            }

            // 执行邮件发送请求
            ret = curl_easy_perform(curl);
            if (ret != CURLE_OK) {
                LOG_ERROR("发送邮件失败: {}", curl_easy_strerror(ret));
                curl_slist_free_all(recipients);
                curl_easy_cleanup(curl);
                return false;
            }

            // 清理资源
            curl_slist_free_all(recipients);
            curl_easy_cleanup(curl);
            LOG_DEBUG("发送邮件成功: 收件人={}, 验证码={}", to, code);
            return true;
        }

    private:
        // 构造邮件正文（HTML格式）
        std::stringstream codeBody(const std::string& to, const std::string& code) {
            std::stringstream ss;
            ss << "Subject: " << _title << "\r\n";          // 邮件主题
            ss << "Content-Type: text/html\r\n";             // 内容类型为HTML
            ss << "\r\n";                                    // 空行分隔头部与正文
            // 正文内容（验证码信息）
            ss << "<html><body>"
               << "<p>你的验证码: <b>" << code << "</b></p>"
               << "<p>验证码将在5分钟后失效.</p>"
               << "</body></html>\r\n";
            return ss;
        }

        // CURL数据读取回调函数（静态成员函数，符合CURL回调签名）
        static size_t callback(char* buffer, size_t size, size_t nitems, void* userdata) {
            std::stringstream* ss = static_cast<std::stringstream*>(userdata);
            ss->read(buffer, size * nitems);  // 从stringstream读取数据到CURL缓冲区
            return ss->gcount();              // 返回实际读取的字节数
        }

    private:
        const std::string _title = "验证码";  // 邮件标题
        mail_settings _settings;              // 邮件服务配置（账号、服务器等）
    };
}  // namespace ltn